﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "StatusBarImpl.h"
#include "IStatusBarPanel.h"
#include "IControl.h"
#include "DebugMessage.h"
#include "GbmpNew.h"
#include "TransferOwnership.h"
#include <QHBoxLayout>
#include <QMenu>
#include "IControlDefinition.h"
#include "StatusBarPanelImpl.h"
#include "ICommand.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

namespace
{
using namespace gcmp;

class FindPanelByName
{
public:
    explicit FindPanelByName(const std::wstring& name) : m_name(name) {}

    bool operator()(const gcmp::IStatusBarPanel* pPanel)
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pPanel, L"pPanel不能为空",L"GDMPLab",L"2024-03-30");
        return pPanel->GetPanelId() == m_name;
    }

private:
    std::wstring m_name;
};

}

namespace gcmp
{

StatusBarImpl::StatusBarImpl(QWidget* pParent)
    : QStatusBar(pParent)
{
    QWidget* pWidget = NEW_AS_QT_CHILD(QWidget, this);
    m_pLayout = NEW_AS_QT_LAYOUT(QHBoxLayout, this);
    m_pLayout->setContentsMargins(QMargins());
    m_pLayout->addStretch(1000000);         // 中间的弹簧区分左右
    pWidget->setLayout(m_pLayout);
    addPermanentWidget(pWidget, 1000000);   // 用1000000充满整个状态栏，否则permanentWidget默认只占据右边，到不了最左边
}

StatusBarImpl::~StatusBarImpl()
{
}

IStatusBarPanel* StatusBarImpl::GetPanel(const std::wstring& panelName) const
{
    auto searchPanelLeft = std::find_if(m_leftPanels.begin(), m_leftPanels.end(), FindPanelByName(panelName));
    if (searchPanelLeft != m_leftPanels.end())
    {
        return *searchPanelLeft;
    }
    else
    {
        auto searchPanelRight = std::find_if(m_rightPanels.begin(), m_rightPanels.end(), FindPanelByName(panelName));
        return (searchPanelRight != m_rightPanels.end()) ? *searchPanelRight : nullptr;
    }
}

bool StatusBarImpl::AppendPanel(OwnerPtr<IStatusBarPanel> pPanel, StatusBarAlignment alignment)
{
    StatusBarPanelImpl* pWidget = dynamic_cast<StatusBarPanelImpl*>(pPanel.get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pWidget, L"pWidget不能为空",L"GDMPLab",L"2024-03-30");

    const std::wstring panelName = pPanel->GetPanelId();

    auto iter = std::find_if(m_leftPanels.begin(), m_leftPanels.end(), FindPanelByName(panelName));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(iter == m_leftPanels.end(), L"状态栏插入失败，与已经存在的状态栏重名!",L"GDMPLab",L"2024-03-30");
    iter = std::find_if(m_rightPanels.begin(), m_rightPanels.end(), FindPanelByName(panelName));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(iter == m_rightPanels.end(), L"状态栏插入失败，与已经存在的状态栏重名!",L"GDMPLab",L"2024-03-30");

    if (alignment == StatusBarAlignment::Left)
    {
        IStatusBarPanel* pStatusBarPanel = TRANSFER_OWNERSHIP_TO_THIRD_PARTY(pPanel);  // Qt接管所有权
        m_pLayout->insertWidget(static_cast<int>(m_leftPanels.size()), pWidget, pWidget->GetStretch());
        m_leftPanels.push_back(pStatusBarPanel);
    }
    else
    {
        IStatusBarPanel* pStatusBarPanel = TRANSFER_OWNERSHIP_TO_THIRD_PARTY(pPanel);  // Qt接管所有权
        m_pLayout->insertWidget(static_cast<int>(m_leftPanels.size() + 1), pWidget, pWidget->GetStretch());      // 弹簧右边
        m_rightPanels.push_back(pStatusBarPanel);
    }
    return true;
}

bool StatusBarImpl::InsertPanel(const std::wstring& followingPanelName, OwnerPtr<IStatusBarPanel> pPanel)
{
    StatusBarPanelImpl* pWidget = dynamic_cast<StatusBarPanelImpl*>(pPanel.get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pWidget, L"pWidget不能为空",L"GDMPLab",L"2024-03-30");

    std::wstring panelName = pPanel->GetPanelId();

    auto searchPanelLeft = std::find_if(m_leftPanels.begin(), m_leftPanels.end(), FindPanelByName(panelName));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(searchPanelLeft == m_leftPanels.end(), L"状态栏插入失败，与已经存在的状态栏重名!",L"GDMPLab",L"2024-03-30");
    auto searchPanelRight = std::find_if(m_rightPanels.begin(), m_rightPanels.end(), FindPanelByName(panelName));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(searchPanelRight == m_rightPanels.end(), L"状态栏插入失败，与已经存在的状态栏重名!",L"GDMPLab",L"2024-03-30");

    auto searchRefPanelLeft = std::find_if(m_leftPanels.begin(), m_leftPanels.end(), FindPanelByName(followingPanelName));
    if (searchRefPanelLeft != m_leftPanels.end())
    {
        // 从左向右的index
        int index = static_cast<int>(std::distance(m_leftPanels.begin(), searchRefPanelLeft));
        IStatusBarPanel* pStatusBarPanel = TRANSFER_OWNERSHIP_TO_THIRD_PARTY(pPanel);      // Qt接管所有权
        m_pLayout->insertWidget(index, pWidget, pWidget->GetStretch());
        m_leftPanels.insert(searchRefPanelLeft, pStatusBarPanel);
    }
    else
    {
        auto searchRefPanelRight = std::find_if(m_rightPanels.begin(), m_rightPanels.end(), FindPanelByName(followingPanelName));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(searchRefPanelRight != m_rightPanels.end(), L"状态栏插入失败，参考状态栏面板不存在!",L"GDMPLab",L"2024-03-30");

        // 从右向左的index
        int rightToLeftIndex = static_cast<int>(std::distance(m_rightPanels.begin(), searchRefPanelRight));
        // 右边区域插入到refPanel的前面，也就是右边
        int leftToRightIndex = static_cast<int>(m_leftPanels.size() + 1 + m_rightPanels.size() - rightToLeftIndex + 1);
        IStatusBarPanel* pStatusBarPanel = TRANSFER_OWNERSHIP_TO_THIRD_PARTY(pPanel);      // Qt接管所有权
        m_pLayout->insertWidget(leftToRightIndex, pWidget, pWidget->GetStretch());
        m_rightPanels.insert(searchRefPanelRight, pStatusBarPanel);
    }
    return true;
}

bool StatusBarImpl::DeletePanel(const std::wstring& panelName)
{
    auto searchPanelLeft = std::find_if(m_leftPanels.begin(), m_leftPanels.end(), FindPanelByName(panelName));
    if (searchPanelLeft != m_leftPanels.end())
    {
        QWidget* pWidget = dynamic_cast<QWidget*>(*searchPanelLeft);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pWidget, L"pWidget是空指针!",L"GDMPLab",L"2024-03-30");

        m_pLayout->removeWidget(pWidget);
        pWidget->deleteLater();
        m_leftPanels.erase(searchPanelLeft);
    }
    else
    {
        auto searchPanelRight = std::find_if(m_rightPanels.begin(), m_rightPanels.end(), FindPanelByName(panelName));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(searchPanelRight != m_rightPanels.end(), L"没有找到要删除的状态栏面板!",L"GDMPLab",L"2024-03-30");
    
        QWidget* pWidget = dynamic_cast<QWidget*>(*searchPanelRight);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pWidget, L"pWidget是空指针!",L"GDMPLab",L"2024-03-30");

        m_pLayout->removeWidget(pWidget);
        pWidget->deleteLater();
        m_rightPanels.erase(searchPanelRight);
    }
    return true;
}

void StatusBarImpl::UpdateControlStatus()
{
    for (auto pPanel : m_leftPanels)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(pPanel, L"pPanel为空",L"GDMPLab",L"2024-03-30");
        pPanel->UpdateControlStatus();
    }
    for (auto pPanel : m_rightPanels)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(pPanel, L"pPanel为空",L"GDMPLab",L"2024-03-30");
        pPanel->UpdateControlStatus();
    }
}

}   // end namespace gcmp
